package com.yxx.strategy.loginStrategyImpl;

import com.yxx.config.properties.GithubProperties;
import com.yxx.constant.LoginConstant;
import com.yxx.entityModel.dto.GitUserInfoDTO;
import com.yxx.entityModel.dto.SocialTokenDTO;
import com.yxx.entityModel.dto.SocialUserInfoDTO;
import com.yxx.entityModel.dto.TokenDTO;
import com.yxx.entityModel.vo.request.CodeRequest;
import com.yxx.enums.LoginTypeEnum;
import com.yxx.exception.ServiceException;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Service;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * Github登录策略
 * @author yuxiangxun
 * @date 2025/2/6
 * @apiNote
 */
@Service("githubLoginStrategyImpl")
public class GithubLoginStrategyImpl extends AbstractLoginStrategyImpl{

    @Resource
    private GithubProperties githubProperties;

    @Resource
    private RestTemplate restTemplate;

    /**
     * 获取 Github 第三方Token
     * @param data data
     * @return
     */
    @Override
    public SocialTokenDTO getSocialTokenDTO(CodeRequest data) {
        // 获取 Github 的 Token
        TokenDTO githubTokenDTO = getGithubToekn(data.getCode());
        // 返回 第三方 Token 信息
        return SocialTokenDTO.builder()
                .accessToken(githubTokenDTO.getAccess_token())
                .loginType(LoginTypeEnum.GITHUB.getLoginType())
                .build();
    }

    /**
     * 获取 Github 的 Token
     * @param code
     * @return
     */
    private TokenDTO getGithubToekn(String code){
        // 根据 code 换取 accessToken
        MultiValueMap<String,String> githubData = new LinkedMultiValueMap<>();
        // Github 的 Token 请求参数  从配置文件中获取
        githubData.add(LoginConstant.CLIENT_ID,githubProperties.getClientId());
        githubData.add(LoginConstant.CLIENT_SECRET,githubProperties.getClientSecret());
        githubData.add(LoginConstant.CODE,code);
        githubData.add(LoginConstant.REDIRECT_URI,githubProperties.getRedirectUrl());
        HttpHeaders headers = new HttpHeaders();
        headers.setAccept(List.of(MediaType.APPLICATION_JSON));
        HttpEntity<MultiValueMap<String,String>> requestEntity = new HttpEntity<>(githubData,headers);
        try {
            return restTemplate.exchange(githubProperties.getAccessTokenUrl(),
                    HttpMethod.POST,
                    requestEntity,
                    TokenDTO.class).getBody();
        } catch (Exception e) {
            throw new ServiceException("Github登录错误");
        }
    }

    /**
     * 获取 Github 第三方用户信息
     * @param socialTokenDTO 第三方token
     * @return {@link SocialUserInfoDTO} 第三方用户信息
     */
    @Override
    public SocialUserInfoDTO getSocialUserInfo(SocialTokenDTO socialTokenDTO) {
        // 请求头参数
        HttpHeaders headers = new HttpHeaders();
        headers.set("Authorization", "Bearer" + socialTokenDTO.getAccessToken());
        HttpEntity<Map<String,String>> requestEntity = new HttpEntity<>(null,headers);
        // Github 用户信息
        GitUserInfoDTO gitUserInfoDTO = restTemplate.exchange(
                githubProperties.getUserInfoUrl(),
                HttpMethod.GET,
                requestEntity,
                GitUserInfoDTO.class
        ).getBody();
        // 返回用户信息
        return SocialUserInfoDTO.builder()
                .avatar(Objects.requireNonNull(gitUserInfoDTO).getAvatar_url())
                .id(gitUserInfoDTO.getId())
                .nickname(gitUserInfoDTO.getLogin())
                .build();
    }
}
